package com.heima.search.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.article.feign.ApArticleFeign;
import com.heima.common.dtos.ResponseResult;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.search.dtos.ArticleDocumentVo;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.search.pojos.ArticleDocument;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.repository.ArticleDocumentRepository;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.common.BeanHelper;
import com.heima.utils.common.ThreadLocalUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class ArticleSearchServiceImpl implements ArticleSearchService {
    @Autowired
    private ElasticsearchRestTemplate restTemplate;
    @Autowired
    private ApArticleFeign apArticleFeign;
    @Autowired
    private ArticleDocumentRepository articleDocumentRepository;
    @Autowired
    private ApUserSearchService apUserSearchService;

    @Override
    public ResponseResult<List<ArticleDocumentVo>> search(UserSearchDto dto) {
        if(dto.getPageSize()==0)dto.setPageSize(20);

        //一、创建查询构造器对象:用于封装所有条件
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        //封装条件到查询构造器中（***）
        //1.1 query条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must( QueryBuilders.matchQuery("title",dto.getSearchWords()) );
        boolQueryBuilder.must( QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime()) );
        queryBuilder.withQuery(boolQueryBuilder);

        //1.2 分页条件
        /**
         * page: 当前页码    from=page*size
         * size: 页面大小
         */
        queryBuilder.withPageable(PageRequest.of(0,dto.getPageSize()));

        //1.3 排序条件
        queryBuilder.withSort(SortBuilders.fieldSort("publishTime").order(SortOrder.DESC));

        //1.4 高亮条件
        HighlightBuilder.Field field = new HighlightBuilder.Field("title");
        field.preTags("<font style='color: red; font-size: inherit;'>");
        field.postTags("</font>");

        queryBuilder.withHighlightFields(field);

        //二、从查询构造器中获取查询对象
        NativeSearchQuery searchQuery = queryBuilder.build();

        //三、使用查询对象执行搜索，获取结果
        SearchHits<ArticleDocument> searchHits = restTemplate.search(searchQuery, ArticleDocument.class);

        //四、结果处理并返回
        System.out.println("命中结果数："+searchHits.getTotalHits());

        //遍历所有SearchHits
        List<ArticleDocumentVo>  articleDocumentVoList = new ArrayList<>();
        for(SearchHit<ArticleDocument> hit : searchHits){
            //获取内容（_source）
            ArticleDocument articleDocument = hit.getContent();

            //拷贝数据
            ArticleDocumentVo articleDocumentVo = BeanHelper.copyProperties(articleDocument, ArticleDocumentVo.class);

            //另外取出高亮内容
            List<String> titles = hit.getHighlightFields().get("title");
            if(CollectionUtils.isNotEmpty(titles)){
                //设置高亮标题
                articleDocumentVo.setH_title(titles.get(0));
            }

            articleDocumentVoList.add(articleDocumentVo);
        }


        //新增用户搜索记录
        ApUser apUser = (ApUser)ThreadLocalUtils.get();
        if(apUser!=null){
            apUserSearchService.insert(apUser.getId(),dto.getSearchWords());
        }

        return ResponseResult.okResult(articleDocumentVoList);
    }

    @Override
    public void saveToES(Long articleId) {
        //根据文章ID查询App文章数据（ApArticle）
        ResponseResult<ApArticle> responseResult = apArticleFeign.findById(articleId);
        if(responseResult.getCode().equals(200)){
            ApArticle apArticle = responseResult.getData();
            //拷贝数据到ArticleDocument
            ArticleDocument articleDocument = BeanHelper.copyProperties(apArticle, ArticleDocument.class);
            //保存ArticleDocument
            articleDocumentRepository.save(articleDocument);
        }

    }

    @Override
    public void removeFromES(Long articleId) {
        articleDocumentRepository.deleteById(articleId);
    }
}
